package com.free4inno.knowledgems.utils;
import com.free4inno.knowledgems.dao.ResourceDAO;
import com.free4inno.knowledgems.domain.Resource;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.layout.font.FontProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.itextpdf.html2pdf.HtmlConverter;
import javax.imageio.ImageIO;


/**
 * @author : liuxinyuan
 * @date : 10:51 2021/11/23
 */

@Slf4j
@Component
public class PdfUtils {

    @Value("${pdf.temp.path}")
    private String pdfTempPath;

    @Value("${pdf.font.path}")
    private String pdfFontPath;

    @Value("${file.environment}")
    private String fileEnvironment;

    @Value("${pdf.baseuri}")
    private String BASEURI;

    @Autowired
    private ResourceDAO resourceDao;

    private String title;


    public String toPdf(int id) throws Exception {
        String tempSavePath = getRealPath(pdfTempPath);
        //每次执行的时候先清一下缓存
        delAllFile(pdfTempPath);
        //判断文件夹是否被创建，未被创建则自动创建
        File folder = new File(tempSavePath);
        if (!folder.exists() && !folder.isDirectory()) {
            folder.mkdirs();
        }
        //判断文件夹是否被创建，未被创建则自动创建
        File folder2 = new File(BASEURI + "img/");
        if (!folder2.exists() && !folder2.isDirectory()) {
            folder2.mkdirs();
        }
        //删除图片缓存文件夹的所有图片
        delAllFile(BASEURI + "img/");

        //数据库操作，获取正文标签
        Resource resource = resourceDao.findAllById(id);
        String htmlHead = "<h1>" + resource.getTitle() + "</h1>";
        title = resource.getTitle();
        String htmlwriter = "<h4>" + resource.getUserName() + "</h4>";
        String htmltime = "<h4>时间：" + resource.getCreateTime() + "</h4>";
        String htmlText = resource.getText();
        htmlText = htmlHead + htmltime + htmlText;

        htmlText = multiple_format_support(htmlText, "png");
        htmlText = multiple_format_support(htmlText, "jpg");
        htmlText = multiple_format_support(htmlText, "jpeg");
        htmlText = multiple_format_support(htmlText, "gif");
        htmlText = multiple_format_support(htmlText, "webp");
        htmlText = multiple_format_support(htmlText, "bitmap");


        createPdf(BASEURI, htmlText, pdfTempPath + id + ".pdf");

        return tempSavePath;
    }

    //支持多种格式图片
    public String multiple_format_support(String htmlText, String type) throws Exception {
        //对图片进行处理操作，首先用正则式替换标签的图片路径
        //定义set集合,实现去重效果
        ArrayList<String> result = new ArrayList<String>();

        //定义正则表达式
        String regex = "src=\"(.{0,200}." + type + ")\"";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(htmlText);

        //发现匹配的字符串,存入数组中
        while (matcher.find()) {
            result.add(matcher.group(1));
        }
        for (int i = 0; i < result.size(); i++) {
            String temp = result.get(i);
            htmlText = htmlText.replace(temp, "img/" + i + "." + type);
            temp = temp.replace("..", "http://zhi.free4inno.com");
            try {
                download_img(temp, i, type);
            } catch (Exception e) {
                download_img("http://xiaoliu1205.com/img/image_loss." + type, i, type);
            }

            if (type != "webp") {
                //下载完图片后，对图片像素进行压缩
                //首先判断图片宽度是否超过800像素,防止图片出界
                if (check_image_size(1, BASEURI + "img/" + i + "." + type) > 740) {
                    double img_width = check_image_size(1, BASEURI + "img/" + i + "." + type);
                    double img_height = check_image_size(0, BASEURI + "img/" + i + "." + type);
                    double xishu = img_width / 740;
                    htmlText = htmlText.replace(Integer.toString((int) img_width), Integer.toString((int) (img_width / xishu)));
                    htmlText = htmlText.replace(Integer.toString((int) img_height), Integer.toString((int) (img_height / xishu)));
                }

                //对长度进行限制使得整体比较美观
                if (check_image_size(0, BASEURI + "img/" + i + "." + type) > 400) {
                    double img_width = check_image_size(1, BASEURI + "img/" + i + "." + type);
                    double img_height = check_image_size(0, BASEURI + "img/" + i + "." + type);
                    double xishu = img_height / 400;
                    htmlText = htmlText.replace(Integer.toString((int) img_width), Integer.toString((int) (img_width / xishu)));
                    htmlText = htmlText.replace(Integer.toString((int) img_height), Integer.toString((int) (img_height / xishu)));
                }
            }
        }
        return htmlText;
    }

    public void createPdf(String baseUri, String html, String dest) throws IOException {
        ConverterProperties props = new ConverterProperties();
        FontProvider fp = new FontProvider();
        fp.addStandardPdfFonts();
        fp.addDirectory(pdfFontPath);
        props.setFontProvider(fp);
        props.setBaseUri(baseUri);
        HtmlConverter.convertToPdf(html, new FileOutputStream(dest), props);
    }

    public String getRealPath(String path) {
        // path & OS
        String realPath = "";
        if (fileEnvironment.equals("dev")) {
            // get system run path
            String runPath = System.getProperty("user.dir");
            realPath = runPath + '/' + path;
        } else if (fileEnvironment.equals("prod")) {
            realPath = path;
        }
        return realPath;
    }

    //下载图片的工具类
    public void download_img(String urlString, int i, String type) throws Exception {
        // 构造URL
        URL url = new URL(urlString);
        // 打开连接
        URLConnection con = url.openConnection();
        // 输入流
        InputStream is = con.getInputStream();
        // 1000K的数据缓冲
        byte[] bs = new byte[1024000];
        // 读取到的数据长度
        int len;
        // 输出的文件流
        String filename = BASEURI + "img/" + i + "." + type;  //下载路径及下载图片名称
        File file = new File(filename);
        FileOutputStream os = new FileOutputStream(file, true);
        // 开始读取
        while ((len = is.read(bs)) != -1) {
            os.write(bs, 0, len);
        }
        System.out.println(i);
        // 完毕，关闭所有链接
        os.close();
        is.close();
    }

    //删除全部文件的工具类
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
                delFolder(path + "/" + tempList[i]);//再删除空文件夹
                flag = true;
            }
        }
        return flag;
    }

    //删除文件夹
    public static void delFolder(String folderPath) {
        try {
            delAllFile(folderPath); //删除完里面所有内容
            String filePath = folderPath;
            filePath = filePath.toString();
            java.io.File myFilePath = new java.io.File(filePath);
            myFilePath.delete(); //删除空文件夹
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static int check_image_size(int isWidth, String path) {
        File file = new File(path);
        FileChannel fc = null;
        if (file.exists() && file.isFile()) {
            try {
                FileInputStream fs = new FileInputStream(file);
                fc = fs.getChannel();
                System.out.println(fc.size() + "-----fc.size()");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //System.out.println(file.length() + "-----file.length  B");
        //System.out.println(file.length() * 1024 + "-----file.length  kb");
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        int width = bi.getWidth();
        int height = bi.getHeight();
        //System.out.println("宽：像素-----" + width + "高：像素" + height);
        if (isWidth == 1) {
            return width;
        } else {
            return height;
        }
    }

    public String get_title() {
        return this.title;
    }
}